using System;
using System.Data;
using System.Data.Common;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.IO;
using System.IO.Compression;
using Microsoft.Practices.EnterpriseLibrary.Data;
using ViewStateEliminator.Configuration;
using ViewStateEliminator.Data;
using System.Configuration;
namespace ViewStateEliminator.UI
{
    /// <summary>
    /// This class overrides LoadPageStateFromPersistenceMedium & SavePageStateToPersistenceMedium to
    /// circumvent streaming out the viewstate string to the client. Depeding on the Appsettings keys determine what
    /// the persistance medium is, and if the viewstate string should be in compressed. 
    /// </summary>
    /// <remarks>
    /// Keys:
    /// viewstateelimintorcompress - when set to true, viewstate will be gziped.
    /// viewstateelimintormode - has currently two values {database, session}. Database mode will persist viewtate to a database table, Session will persist it to session.
    ///</remarks>
    public class BaseNoViewStatePage : System.Web.UI.Page
    {
        private IViewstateStorage _viewstateStorage;
        private ViewStateConfiguration _config;

        protected override object LoadPageStateFromPersistenceMedium()
        {
            object retVal;
            string id = Request.Form["__VIEWSTATE"];
            byte[] bytes = null;
            _config = (ViewStateConfiguration)ConfigurationManager.GetSection("ViewStateConfiguration");
            this._viewstateStorage = ViewstateStorageFactory.GetStorageMedium();
            bytes = Convert.FromBase64String(this._viewstateStorage.Get(id).Value);
            if (_config.UseCompression)
                bytes = Util.Decompress(bytes);
            LosFormatter formatter = new LosFormatter();
            retVal = formatter.Deserialize(Convert.ToBase64String(bytes));
            return retVal;
        }
        protected override void SavePageStateToPersistenceMedium(object viewState)
        {
            this._viewstateStorage = ViewstateStorageFactory.GetStorageMedium();
            _config = (ViewStateConfiguration)ConfigurationManager.GetSection("ViewStateConfiguration");
            LosFormatter formatter = new LosFormatter();
            StringWriter writer = new StringWriter();
            formatter.Serialize(writer, viewState);
            string viewStateString = writer.ToString();
            byte[] bytes = Convert.FromBase64String(viewStateString);
            if (_config.UseCompression)
                bytes = Util.Compress(bytes);
            string viewstateBase64 = Convert.ToBase64String(bytes);
            string id = ViewstateStorageFactory.GetUserUniqueID().GetUniqueID();
            this._viewstateStorage.Add(new KeyValuePair<object, string>(id, viewstateBase64));
            ClientScript.RegisterHiddenField("__VIEWSTATE", id);
        }
    }


    /// <summary>
    /// Helper functions used by ViewStateEliminator.
    /// </summary>
    public static class Util
    {

        // Compresion Functions referenced from Dario Solera
        // www.codeproject.com/aspnet/ViewStateCompression.asp
        #region "Compression"
        /// <summary>
        /// Returns an array of bytes compressed by GZIP
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] Compress(byte[] data)
        {
            MemoryStream output = new MemoryStream();
            GZipStream gzip = new GZipStream(output,
                              CompressionMode.Compress, true);
            gzip.Write(data, 0, data.Length);
            gzip.Close();
            return output.ToArray();
        }
        /// <summary>
        /// Returns an array of bytes Decompressed by GZIP
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] Decompress(byte[] data)
        {
            MemoryStream input = new MemoryStream();
            input.Write(data, 0, data.Length);
            input.Position = 0;
            GZipStream gzip = new GZipStream(input,
                              CompressionMode.Decompress, true);
            MemoryStream output = new MemoryStream();
            byte[] buff = new byte[64];
            int read = -1;
            read = gzip.Read(buff, 0, buff.Length);
            while (read > 0)
            {
                output.Write(buff, 0, read);
                read = gzip.Read(buff, 0, buff.Length);
            }
            gzip.Close();
            return output.ToArray();
        }
        #endregion
    }
}
